package com.ying.tests.AAAVIP;

import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * 自定义类加载器
 */
public class MyClassLoader extends ClassLoader {

    private String classPath;

    public MyClassLoader(String classPath) {
        this.classPath = classPath;
    }

    /**
     * 将.class文件存放的路径拼接完整，如：D:/项目地址/包路径/xxx.class
     */
    private byte[] loadByte(String name) throws Exception {
        name = name.replaceAll("\\.", "/");
        FileInputStream fileIn = new FileInputStream(classPath + "/" + name + ".class");
        int len = fileIn.available();
        byte[] data = new byte[len];
        fileIn.read(data);
        fileIn.close();
        return data;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] data = loadByte(name);
            // defineClass将一个字节数组转为Class对象，这个字节数组是class文件读取后最终的字节数组。
            return defineClass(name, data, 0, data.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ClassNotFoundException();
        }
    }

    public static void main(String[] args) throws Exception {
        // 初始化自定义类加载器，会先初始化父类 ClassLoader，
        // 其中会把自定义类加载器的父加载器设置为应用程序类加载器 AppClassLoader

        // 创建个项目地址
        MyClassLoader myClassLoader = new MyClassLoader("D:/Work/IdeaProjects/Vipkid/my/tests");
        // 创建个项目中User.class存放的地址
        Class clazz = myClassLoader.loadClass("com.ying.tests.AAAVIP.User");// 过程中会调用findClass方法
        Object obj = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("login", new Class[0]);
        method.setAccessible(true);
        method.invoke(obj, new Object[]{});

        // 类加载时先去appClassLoader找(项目启动时去加载)，如果找不到就会去我们创建的目录下去加载，如果加载到，就把我们创建的类设置为应用类加载器
        System.out.println(clazz.getClassLoader().getClass().getName());

    }
}
